var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var ecs;
(function (ecs) {
    var Aspect = (function () {
        function Aspect() {
        }
        return Aspect;
    }());
    ecs.Aspect = Aspect;
    var Builder = (function () {
        function Builder() {
        }
        Builder.prototype.build = function (world) {
            var tf = world.getComponentManager().typeFactory;
            var aspect = new Aspect();
            return aspect;
        };
        Builder.associate = function (tf, types, componentBits) {
            for (var i in types) {
                componentBits.set(tf.getIndexFor(types[i]));
            }
        };
        return Builder;
    }());
    ecs.Builder = Builder;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var BaseSystem = (function () {
        function BaseSystem() {
        }
        BaseSystem.prototype.setWorld = function (world) {
            this._world = world;
        };
        BaseSystem.prototype.begin = function () { };
        BaseSystem.prototype.process = function () {
            if (this.checkProcessing()) {
                this.begin();
                this.processSystem();
                this.end();
            }
        };
        BaseSystem.prototype.end = function () { };
        BaseSystem.prototype.checkProcessing = function () {
            return true;
        };
        BaseSystem.prototype.initialize = function () { };
        BaseSystem.prototype.dispose = function () { };
        return BaseSystem;
    }());
    ecs.BaseSystem = BaseSystem;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var AspectSubscriptionManager = (function (_super) {
        __extends(AspectSubscriptionManager, _super);
        function AspectSubscriptionManager() {
            var _this = _super.call(this) || this;
            _this._subscriptions = new ecs.Bag();
            _this._changed = new ecs.NumberBag();
            _this._deleted = new ecs.NumberBag();
            _this._subscriptionMap = new ecs.Map([]);
            return _this;
        }
        AspectSubscriptionManager.prototype.processSystem = function () { };
        AspectSubscriptionManager.prototype.processNotify = function (changedBits, deletedBits) {
            this.toEntityIntBags(changedBits, deletedBits);
        };
        AspectSubscriptionManager.prototype.toEntityIntBags = function (changed, deleted) {
            changed.toIntBagIdCid(this._world.getComponentManager(), this._changed);
            deleted.toIntBag(this._deleted);
            changed.clear();
            deleted.clear();
        };
        AspectSubscriptionManager.prototype.get = function (builder) {
            var subscription = this._subscriptionMap.get(builder);
            return (subscription != null) ? subscription : this.createSubscription(builder);
        };
        AspectSubscriptionManager.prototype.createSubscription = function (builder) {
            var entitySubscription = new ecs.EntitySubscription(this._world, builder);
            this._subscriptionMap.add(builder, entitySubscription);
            this._subscriptions.add(entitySubscription);
            this._world.getComponentManager().synchronize(entitySubscription);
            return entitySubscription;
        };
        return AspectSubscriptionManager;
    }(ecs.BaseSystem));
    ecs.AspectSubscriptionManager = AspectSubscriptionManager;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var BaseComponentMapper = (function () {
        function BaseComponentMapper(type) {
            this.type = type;
        }
        BaseComponentMapper.prototype.set = function (entityId, value) {
            if (value) {
                return this.create(entityId);
            }
            else {
                this.remove(entityId);
                return null;
            }
        };
        return BaseComponentMapper;
    }());
    ecs.BaseComponentMapper = BaseComponentMapper;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var BaseEntitySystem = (function (_super) {
        __extends(BaseEntitySystem, _super);
        function BaseEntitySystem() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        return BaseEntitySystem;
    }(ecs.BaseSystem));
    ecs.BaseEntitySystem = BaseEntitySystem;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var BatchChangeProcessor = (function () {
        function BatchChangeProcessor(world) {
            this.changed = new ecs.BitVector();
            this._deleted = new ecs.BitVector();
            this._world = world;
            this._asm = world.getAspectSubscriptionManager();
        }
        BatchChangeProcessor.prototype.update = function () {
            while (!this.changed.isEmpty() || !this._deleted.isEmpty()) {
                this._asm.processNotify(this.changed, this._deleted);
                this.purgeComponents();
            }
        };
        BatchChangeProcessor.prototype.purgeComponents = function () {
        };
        return BatchChangeProcessor;
    }());
    ecs.BatchChangeProcessor = BatchChangeProcessor;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var Component = (function () {
        function Component() {
        }
        return Component;
    }());
    ecs.Component = Component;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var ComponentManager = (function (_super) {
        __extends(ComponentManager, _super);
        function ComponentManager(entityContainerSize) {
            var _this = _super.call(this) || this;
            _this._mappers = new ecs.Bag();
            _this.entityToIdentity = new ecs.NumberBag(entityContainerSize);
            _this.typeFactory = new ecs.ComponentTypeFactory(_this, entityContainerSize);
            return _this;
        }
        ComponentManager.prototype.processSystem = function () { };
        ComponentManager.prototype.getIdentity = function (entityId) {
            return this.entityToIdentity.get(entityId);
        };
        ComponentManager.prototype.getMapper = function (mapper) {
            var type = this.typeFactory.getTypeFor(mapper);
            return this._mappers.get(type.getIndex());
        };
        ComponentManager.prototype.registerComponentType = function (ct, capacity) {
            var index = ct.getIndex();
            var mapper = new ecs.ComponentMapper(typeof (ct), this._world);
            mapper.components.ensureCapacity(capacity);
            this._mappers.set(index, mapper);
        };
        ComponentManager.prototype.synchronize = function (es) {
        };
        ComponentManager.prototype.ensureCapacity = function (newSize) {
            this.typeFactory.initialMapperCapacity = newSize;
            this.entityToIdentity.ensureCapacity(newSize);
            for (var m in this._mappers) {
                var mapper = this._mappers[m];
                mapper.components.ensureCapacity(newSize);
            }
        };
        return ComponentManager;
    }(ecs.BaseSystem));
    ecs.ComponentManager = ComponentManager;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var ComponentMapper = (function (_super) {
        __extends(ComponentMapper, _super);
        function ComponentMapper(type, world) {
            var _this = _super.call(this, world.getComponentManager().typeFactory.getTypeFor(type)) || this;
            _this.components = new ecs.Bag();
            return _this;
        }
        ComponentMapper.prototype.get = function (entityId) {
            return this.components.get(entityId);
        };
        ComponentMapper.prototype.create = function (entityId) {
            var component = this.get(entityId);
            if (component == null || this._purgatory.unmark(entityId)) {
            }
            return component;
        };
        ComponentMapper.prototype.remove = function (entityId) {
            throw new Error("Method not implemented.");
        };
        return ComponentMapper;
    }(ecs.BaseComponentMapper));
    ecs.ComponentMapper = ComponentMapper;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var ComponentPool = (function () {
        function ComponentPool(type) {
            this._type = type;
            this._cache = new ecs.Bag();
        }
        return ComponentPool;
    }());
    ecs.ComponentPool = ComponentPool;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var ComponentRemover = (function () {
        function ComponentRemover(components, pool) {
            this._components = components;
            this.pool = pool;
        }
        return ComponentRemover;
    }());
    ecs.ComponentRemover = ComponentRemover;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var ComponentType = (function () {
        function ComponentType(type, index) {
            this._index = index;
            this._type = type;
        }
        ComponentType.prototype.getIndex = function () {
            return this._index;
        };
        ComponentType.prototype.getType = function () {
            return this._type;
        };
        return ComponentType;
    }());
    ecs.ComponentType = ComponentType;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var ComponentTypeFactory = (function () {
        function ComponentTypeFactory(cm, entityContainerSize) {
            this._componentTypes = new ecs.Map([]);
            this.types = new ecs.Bag();
            this._cm = cm;
            this.initialMapperCapacity = entityContainerSize;
        }
        ComponentTypeFactory.prototype.getIndexFor = function (c) {
            return this.getTypeFor(c).getIndex();
        };
        ComponentTypeFactory.prototype.getTypeFor = function (c) {
            var type = this._componentTypes.get(c);
            if (type == null)
                type = this.createComponentType(c);
            return type;
        };
        ComponentTypeFactory.prototype.createComponentType = function (c) {
            var type = new ecs.ComponentType(c, this.types.size());
            this._componentTypes.add(c, type);
            this.types.add(type);
            this._cm.registerComponentType(type, this.initialMapperCapacity);
            return type;
        };
        return ComponentTypeFactory;
    }());
    ecs.ComponentTypeFactory = ComponentTypeFactory;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var ConfigurationElement = (function () {
        function ConfigurationElement(item, priority) {
            this.item = item;
            this.itemType = egret.getQualifiedSuperclassName(item);
            this.priority = priority;
        }
        ConfigurationElement.of = function (item, priority) {
            if (priority === void 0) { priority = ecs.Priority.NORMAL; }
            return new ConfigurationElement(item, priority);
        };
        return ConfigurationElement;
    }());
    ecs.ConfigurationElement = ConfigurationElement;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var Entity = (function () {
        function Entity(world, id) {
            this._world = world;
            this.id = id;
        }
        Entity.prototype.getId = function () {
            return this.id;
        };
        Entity.prototype.getWorld = function () {
            return this._world;
        };
        return Entity;
    }());
    ecs.Entity = Entity;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var EntityManager = (function (_super) {
        __extends(EntityManager, _super);
        function EntityManager(initialContainerSize) {
            var _this = _super.call(this) || this;
            _this._recycled = new ecs.BitVector();
            _this._entityBitVectors = new ecs.Bag();
            _this._limbo = new ecs.NumberDeque();
            _this._entities = new ecs.Bag(initialContainerSize);
            return _this;
        }
        EntityManager.prototype.processSystem = function () { };
        EntityManager.prototype.registerEntityStore = function (bv) {
            bv.ensureCapacity(this._entities.getCapacity());
            this._entityBitVectors.add(bv);
        };
        EntityManager.prototype.isActive = function (entityId) {
            return !this._recycled.unsafeGet(entityId);
        };
        EntityManager.prototype.getEntity = function (entityId) {
            return this._entities.get(entityId);
        };
        EntityManager.prototype.createEntityInstance = function () {
            return this.obtain();
        };
        EntityManager.prototype.obtain = function () {
            if (this._limbo.isEmpty()) {
                return this.createEntity(this.nextId++);
            }
            else {
                var id = this._limbo.popFirst();
                this._recycled.unsafeClear(id);
                return this._entities.get(id);
            }
        };
        EntityManager.prototype.createEntity = function (id) {
            var e = new ecs.Entity(this._world, id);
            if (e.id >= this._entities.getCapacity())
                this.growEntityStores();
            this._entities.set(e.id, e);
            return e;
        };
        EntityManager.prototype.growEntityStores = function () {
            var newSize = 2 * this._entities.getCapacity();
            this._entities.ensureCapacity(newSize);
            var cm = this._world.getComponentManager();
            cm.ensureCapacity(newSize);
            for (var i = 0, s = this._entityBitVectors.size(); s > i; i++) {
                this._entityBitVectors.get(i).ensureCapacity(newSize);
            }
        };
        return EntityManager;
    }(ecs.BaseSystem));
    ecs.EntityManager = EntityManager;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var EntitySubscription = (function () {
        function EntitySubscription(world, builder) {
            this.extra = new SubscriptionExtra(builder.build(world), builder);
            this._activeEntityIds = new ecs.BitVector();
            this._entities = new ecs.NumberBag();
            var em = world.getEntityManager();
            em.registerEntityStore(this._activeEntityIds);
        }
        EntitySubscription.prototype.getEntities = function () {
            if (this._entities.isEmpty() && !this._activeEntityIds.isEmpty()) {
                this.rebuildCompressedActives();
            }
            return this._entities;
        };
        EntitySubscription.prototype.rebuildCompressedActives = function () {
            this._activeEntityIds.toIntBag(this._entities);
        };
        return EntitySubscription;
    }());
    ecs.EntitySubscription = EntitySubscription;
    var SubscriptionExtra = (function () {
        function SubscriptionExtra(aspect, aspectReflection) {
            this.aspect = aspect;
            this.aspectReflection = aspectReflection;
        }
        return SubscriptionExtra;
    }());
    ecs.SubscriptionExtra = SubscriptionExtra;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var FluidEntityPlugin = (function () {
        function FluidEntityPlugin() {
        }
        FluidEntityPlugin.prototype.setup = function (b) {
            b.dependsOn(ecs.Priority.HIGH, new ecs.SuperMapper());
            b.register(new ESubscriptionAspectResolver());
        };
        return FluidEntityPlugin;
    }());
    ecs.FluidEntityPlugin = FluidEntityPlugin;
    var ESubscriptionAspectResolver = (function () {
        function ESubscriptionAspectResolver() {
            this._aspectFieldResolver = new ecs.AspectFieldResolver();
        }
        ESubscriptionAspectResolver.prototype.initialize = function (world) {
            this._aspectFieldResolver.initialize(world);
        };
        ESubscriptionAspectResolver.prototype.resolve = function (target, fieldType, field) {
            return null;
        };
        return ESubscriptionAspectResolver;
    }());
    ecs.ESubscriptionAspectResolver = ESubscriptionAspectResolver;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var SystemInvocationStrategy = (function () {
        function SystemInvocationStrategy() {
            this.disabled = new ecs.BitVector();
        }
        SystemInvocationStrategy.prototype.initialize = function () { };
        SystemInvocationStrategy.prototype.setWorld = function (world) {
            this.world = world;
        };
        SystemInvocationStrategy.prototype.setSystems = function (systems) {
            this.systems = systems;
        };
        SystemInvocationStrategy.prototype.updateEntityStates = function () {
            this.world.batchProcessor.update();
        };
        return SystemInvocationStrategy;
    }());
    ecs.SystemInvocationStrategy = SystemInvocationStrategy;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var InvocationStrategy = (function (_super) {
        __extends(InvocationStrategy, _super);
        function InvocationStrategy() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        InvocationStrategy.prototype.process = function () {
            var systemsData = this.systems.getData();
            for (var i = 0, s = this.systems.size(); s > i; i++) {
                if (this.disabled.get(i))
                    continue;
                this.updateEntityStates();
                systemsData[i].process();
            }
            this.updateEntityStates();
        };
        return InvocationStrategy;
    }(ecs.SystemInvocationStrategy));
    ecs.InvocationStrategy = InvocationStrategy;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var Manager = (function (_super) {
        __extends(Manager, _super);
        function Manager() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        Manager.prototype.registerManager = function () {
            this._world.getAspectSubscriptionManager();
        };
        return Manager;
    }(ecs.BaseSystem));
    ecs.Manager = Manager;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var PooledComponent = (function (_super) {
        __extends(PooledComponent, _super);
        function PooledComponent() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        return PooledComponent;
    }(ecs.Component));
    ecs.PooledComponent = PooledComponent;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var SuperMapper = (function () {
        function SuperMapper() {
        }
        return SuperMapper;
    }());
    ecs.SuperMapper = SuperMapper;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var World = (function () {
        function World(configuration) {
            this.partition = new WorldSegment(configuration);
            this.systemsBag = configuration.systems;
            var lcm = this.systemsBag.get(ecs.WorldConfiguration.COMPONENT_MANAGER_IDX);
            var lem = this.systemsBag.get(ecs.WorldConfiguration.ENTITY_MANAGER_IDX);
            var lasm = this.systemsBag.get(ecs.WorldConfiguration.ASPECT_SUBSCRIPTION_MANAGER_IDX);
            this._cm = lcm == null ? new ecs.ComponentManager(configuration.expectedEntityCount()) : lcm;
            this._em = lem == null ? new ecs.EntityManager(configuration.expectedEntityCount()) : lem;
            this.asm = lasm == null ? new ecs.AspectSubscriptionManager() : lasm;
            this._alwaysDelayComponentRemoval = configuration.isAlwaysDelayComponentRemoval();
            this.batchProcessor = new ecs.BatchChangeProcessor(this);
            configuration.initialize(this, this.partition.injector, this.asm);
        }
        World.prototype.getAspectSubscriptionManager = function () {
            return this.asm;
        };
        World.prototype.getComponentManager = function () {
            return this._cm;
        };
        World.prototype.getEntityManager = function () {
            return this._em;
        };
        World.prototype.getMapper = function (type) {
            return this._cm.getMapper(type);
        };
        World.prototype.isAlwaysDelayComponentRemoval = function () {
            return this._alwaysDelayComponentRemoval;
        };
        World.prototype.setDelta = function (delta) {
            this.delta = delta;
        };
        World.prototype.process = function () {
            this.invocationStrategy.process();
        };
        World.prototype.compositionId = function (entityId) {
            return this._cm.getIdentity(entityId);
        };
        World.prototype.setInvocationStrategy = function (invocationStrategy) {
            this.invocationStrategy = invocationStrategy;
            invocationStrategy.setWorld(this);
            invocationStrategy.setSystems(this.systemsBag);
            invocationStrategy.initialize();
        };
        World.prototype.dispose = function () {
            for (var s in this.systemsBag) {
                var system = this.systemsBag[s];
                try {
                    system.dispose();
                }
                catch (err) {
                }
            }
        };
        World.prototype.createEntity = function () {
            var e = this._em.createEntityInstance();
            this.batchProcessor.changed.unsafeSet(e.getId());
            return e;
        };
        return World;
    }());
    ecs.World = World;
    var WorldSegment = (function () {
        function WorldSegment(configuration) {
            this.systems = new ecs.Map([]);
            this.injector = (configuration.injector != null) ? configuration.injector : new ecs.CachedInjector();
        }
        return WorldSegment;
    }());
    ecs.WorldSegment = WorldSegment;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var WorldConfiguration = (function () {
        function WorldConfiguration() {
            this.systems = new ecs.Bag();
            this._expectedEntityCount = 128;
            this.injectables = {};
            this._alwaysDelayComponentRemoval = false;
            this._registered = [];
            this.systems.add(null);
            this.systems.add(null);
            this.systems.add(null);
        }
        WorldConfiguration.prototype.expectedEntityCount = function () {
            return this._expectedEntityCount;
        };
        WorldConfiguration.prototype.setSystem = function (system) {
            this.systems.add(system);
            if (!this._registered.push(system)) {
                var name_1 = egret.getQualifiedSuperclassName(system);
                throw new Error(name_1 + "already added to" + egret.getQualifiedSuperclassName(this));
            }
            return this;
        };
        WorldConfiguration.prototype.setInjector = function (injector) {
            if (!injector)
                throw new Error("Injector must not be null");
            this.injector = injector;
            return this;
        };
        WorldConfiguration.prototype.setInvocationStrategy = function (invocationStrategy) {
            if (invocationStrategy == null)
                throw new Error("null pointer");
            this.invocationStrategy = invocationStrategy;
            return this;
        };
        WorldConfiguration.prototype.isAlwaysDelayComponentRemoval = function () {
            return this._alwaysDelayComponentRemoval;
        };
        WorldConfiguration.prototype.setAlwaysDelayComponentRemoval = function (value) {
            this._alwaysDelayComponentRemoval = value;
        };
        WorldConfiguration.prototype.initialize = function (world, injector, asm) {
            if (!this.invocationStrategy)
                this.invocationStrategy = new ecs.InvocationStrategy();
            this.invocationStrategy.setWorld(world);
            world.invocationStrategy = this.invocationStrategy;
            this.systems.set(WorldConfiguration.COMPONENT_MANAGER_IDX, world.getComponentManager());
            this.systems.set(WorldConfiguration.ENTITY_MANAGER_IDX, world.getEntityManager());
            this.systems.set(WorldConfiguration.ASPECT_SUBSCRIPTION_MANAGER_IDX, asm);
            for (var i = 0; i < this.systems.size(); i++) {
                var system = this.systems.get(i);
                if (system) {
                    world.partition.systems.add(egret.getQualifiedSuperclassName(system), system);
                    system.setWorld(world);
                }
                if (system instanceof ecs.Manager) {
                    system.registerManager();
                }
            }
            injector.initialize(world, this.injectables);
            this.initializeSystems(injector);
            this.invocationStrategy.setSystems(this.systems);
            this.invocationStrategy.initialize();
        };
        WorldConfiguration.prototype.initializeSystems = function (injector) {
            for (var i = 0, s = this.systems.size(); i < s; i++) {
                var system = this.systems.get(i);
                injector.inject(system);
            }
            for (var i = 0, s = this.systems.size(); i < s; i++) {
                var system = this.systems.get(i);
                system.initialize();
            }
        };
        WorldConfiguration.COMPONENT_MANAGER_IDX = 0;
        WorldConfiguration.ENTITY_MANAGER_IDX = 1;
        WorldConfiguration.ASPECT_SUBSCRIPTION_MANAGER_IDX = 2;
        return WorldConfiguration;
    }());
    ecs.WorldConfiguration = WorldConfiguration;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var WorldConfigurationBuilder = (function () {
        function WorldConfigurationBuilder() {
            this._alwaysDelayComponentRemoval = false;
            this.reset();
            this._cache = ecs.InjectionCache.get();
        }
        WorldConfigurationBuilder.prototype.build = function () {
            var config = new ecs.WorldConfiguration();
            this.registerSystem(config);
            this.registerFieldResolvers(config);
            this.registerInvocationStrategies(config);
            config.setAlwaysDelayComponentRemoval(this._alwaysDelayComponentRemoval);
            this.reset();
            return config;
        };
        WorldConfigurationBuilder.prototype.registerInvocationStrategies = function (config) {
            if (this.invocationStrategy != null) {
                config.setInvocationStrategy(this.invocationStrategy);
            }
        };
        WorldConfigurationBuilder.prototype.registerSystem = function (config) {
            for (var i = 0; i < this._systems.size(); i++) {
                var configurationElement = this._systems.get(i);
                config.setSystem(configurationElement.item);
            }
        };
        WorldConfigurationBuilder.prototype.registerFieldResolvers = function (config) {
            if (this._fieldResolvers.size() > 0) {
                var fieldHandler = new ecs.FieldHandler(ecs.InjectionCache.get());
                for (var i = 0; i < this._fieldResolvers.size(); i++) {
                    var configurationElement = this._fieldResolvers.get(i);
                    fieldHandler.addFieldResolver(configurationElement.item);
                }
                config.setInjector(new ecs.CachedInjector().setFieldHandler(fieldHandler));
            }
        };
        WorldConfigurationBuilder.prototype.dependsOn = function (priority) {
            if (priority === void 0) { priority = Priority.NORMAL; }
            var types = [];
            for (var _i = 1; _i < arguments.length; _i++) {
                types[_i - 1] = arguments[_i];
            }
            for (var type in types) {
                try {
                    switch (this._cache.getFieldClassType(types[type])) {
                        case ecs.ClassType.SYSTEM:
                            this.dependsOnSystem(priority, types[type]);
                            break;
                        default:
                            break;
                    }
                }
                catch (err) {
                    throw new Error("Unable to instance" + type + " via reflection.");
                }
            }
            return this;
        };
        WorldConfigurationBuilder.prototype.with = function (priority) {
            if (priority === void 0) { priority = Priority.NORMAL; }
            var systems = [];
            for (var _i = 1; _i < arguments.length; _i++) {
                systems[_i - 1] = arguments[_i];
            }
            this.addSystems(priority, systems);
            return this;
        };
        WorldConfigurationBuilder.prototype.register = function () {
            var fieldResolvers = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                fieldResolvers[_i] = arguments[_i];
            }
            for (var i = 0; i < fieldResolvers.length; i++) {
                var fieldResolver = fieldResolvers[i];
                this._fieldResolvers.add(ecs.ConfigurationElement.of(fieldResolver));
            }
            return this;
        };
        WorldConfigurationBuilder.prototype.dependsOnSystem = function (priority, type) {
            if (!this.containsType(this._systems, egret.getQualifiedSuperclassName(type))) {
                this._systems.add(ecs.ConfigurationElement.of(type, priority));
            }
        };
        WorldConfigurationBuilder.prototype.addSystems = function (priority, systems) {
            for (var i = 0; i < systems.length; i++) {
                var system = systems[i];
                if (this.containsType(this._systems, egret.getQualifiedSuperclassName(system))) {
                    throw new Error("System of type " + system + " registered twice. Only once allowed.");
                }
                this._systems.add(new ecs.ConfigurationElement(system, priority));
            }
        };
        WorldConfigurationBuilder.prototype.containsType = function (items, type) {
            for (var i = 0; i < items.size(); i++) {
                if (items.get(i).itemType == type)
                    return true;
            }
            return false;
        };
        WorldConfigurationBuilder.prototype.reset = function () {
            this.invocationStrategy = null;
            this._fieldResolvers = new ecs.Bag();
            this._systems = new ecs.Bag();
            this._alwaysDelayComponentRemoval = false;
        };
        WorldConfigurationBuilder.prototype.alwaysDelayComponentRemoval = function (value) {
            this._alwaysDelayComponentRemoval = value;
            return this;
        };
        return WorldConfigurationBuilder;
    }());
    ecs.WorldConfigurationBuilder = WorldConfigurationBuilder;
    var Priority = (function () {
        function Priority() {
        }
        Priority.LOWEST = Number.MIN_VALUE;
        Priority.LOW = -10000;
        Priority.OPERATIONS = -1000;
        Priority.NORMAL = 0;
        Priority.HIGH = 10000;
        Priority.HIGHEST = Number.MAX_VALUE;
        return Priority;
    }());
    ecs.Priority = Priority;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var AspectFieldResolver = (function () {
        function AspectFieldResolver() {
        }
        AspectFieldResolver.prototype.initialize = function (world) {
            throw new Error("Method not implemented.");
        };
        AspectFieldResolver.prototype.resolve = function (target, fieldType, field) {
            throw new Error("Method not implemented.");
        };
        return AspectFieldResolver;
    }());
    ecs.AspectFieldResolver = AspectFieldResolver;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var CachedClass = (function () {
        function CachedClass(clazz) {
            this.clazz = clazz;
        }
        return CachedClass;
    }());
    ecs.CachedClass = CachedClass;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var CachedInjector = (function () {
        function CachedInjector() {
            this._cache = ecs.InjectionCache.get();
        }
        CachedInjector.prototype.getRegistered = function (id) {
            return this._injectables[id];
        };
        CachedInjector.prototype.initialize = function (world, injectables) {
            this._injectables = injectables;
            if (this._fieldHandler == null)
                this._fieldHandler = new ecs.FieldHandler(this._cache);
            this._fieldHandler.initialize(world, injectables);
        };
        CachedInjector.prototype.inject = function (target) {
            try {
            }
            catch (err) {
                throw new Error("Error while wiring" + err);
            }
        };
        CachedInjector.prototype.injectField = function (target, field, faileOnNotInjected) {
        };
        CachedInjector.prototype.getAllInjectableFields = function (cachedClass) {
            var declaredFields = cachedClass.allFields;
            if (declaredFields == null) {
                var fieldList = new Array();
                var clazz = cachedClass.clazz;
                this.collectDeclaredInjectableFields(fieldList, clazz);
                while (cachedClass.injectInherited) {
                    this.collectDeclaredInjectableFields(fieldList, clazz);
                }
                cachedClass.allFields = declaredFields = fieldList;
            }
            return declaredFields;
        };
        CachedInjector.prototype.collectDeclaredInjectableFields = function (fieldList, clazz) {
            try {
            }
            catch (err) {
                throw new Error("Error while wiring" + err);
            }
        };
        CachedInjector.prototype.isInjectable = function (target) {
            throw new Error("Method not implemented.");
        };
        CachedInjector.prototype.setFieldHandler = function (fieldHandler) {
            throw new Error("Method not implemented.");
        };
        return CachedInjector;
    }());
    ecs.CachedInjector = CachedInjector;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var ClassType;
    (function (ClassType) {
        ClassType[ClassType["MAPPER"] = 0] = "MAPPER";
        ClassType[ClassType["SYSTEM"] = 1] = "SYSTEM";
        ClassType[ClassType["WORLD"] = 2] = "WORLD";
        ClassType[ClassType["CUSTOM"] = 3] = "CUSTOM";
    })(ClassType = ecs.ClassType || (ecs.ClassType = {}));
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var FieldHandler = (function () {
        function FieldHandler(cache, fieldResolvers) {
            this._cache = cache;
            if (fieldResolvers) {
                this.fieldResolvers = fieldResolvers;
            }
            else {
                this.fieldResolvers = new ecs.Bag();
            }
        }
        FieldHandler.prototype.initialize = function (world, injectables) {
            var fieldResolveFound = false;
            for (var i = 0, s = this.fieldResolvers.size(); i < s; i++) {
                var fieldResolver = this.fieldResolvers.get(i);
                if (egret.is(fieldResolver, "UseInjectionCache")) {
                    fieldResolver.setCache(this._cache);
                }
                if (egret.is(fieldResolver, "PojoFieldResolver")) {
                    fieldResolver.setPojos(injectables);
                    fieldResolveFound = true;
                }
                fieldResolver.initialize(world);
            }
            if (injectables && Object.keys(injectables).length != 0 && !fieldResolveFound) {
                throw new Error("FieldHandler lacks resolver capable of dealing with your custom injectables. Register a WiredFieldResolver or PojoFieldResolver with your FieldHandler");
            }
        };
        FieldHandler.prototype.addFieldResolver = function (fieldResolver) {
            this.fieldResolvers.add(fieldResolver);
        };
        return FieldHandler;
    }());
    ecs.FieldHandler = FieldHandler;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var InjectionCache = (function () {
        function InjectionCache() {
            this._fieldClassTypeCache = new ecs.Map([]);
            this._classCache = new ecs.Map([]);
        }
        InjectionCache.get = function () {
            if (!this._instance)
                this._instance = new InjectionCache();
            return this._instance;
        };
        InjectionCache.prototype.getFieldClassType = function (fieldType) {
            var injectionType = this._fieldClassTypeCache[fieldType];
            if (!injectionType) {
                if (ecs.ClassReflection.isAssignableFrom(ecs.ComponentMapper, fieldType)) {
                    injectionType = ecs.ClassType.MAPPER;
                }
                else if (ecs.ClassReflection.isAssignableFrom(ecs.BaseSystem, fieldType)) {
                    injectionType = ecs.ClassType.SYSTEM;
                }
                else if (ecs.ClassReflection.isAssignableFrom(ecs.World, fieldType)) {
                    injectionType = ecs.ClassType.WORLD;
                }
                else {
                    injectionType = ecs.ClassType.CUSTOM;
                }
                this._fieldClassTypeCache[fieldType] = injectionType;
            }
            return injectionType;
        };
        InjectionCache.prototype.getCachedClass = function (clazz) {
            var cachedClass = this._classCache.get(clazz);
            if (cachedClass == null) {
                cachedClass = new ecs.CachedClass(clazz);
                this._classCache.add(clazz, cachedClass);
            }
            return cachedClass;
        };
        return InjectionCache;
    }());
    ecs.InjectionCache = InjectionCache;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var EntityLinkManager = (function (_super) {
        __extends(EntityLinkManager, _super);
        function EntityLinkManager(processSitesEvenIfNoListener, fireEventsOnRegistration) {
            if (processSitesEvenIfNoListener === void 0) { processSitesEvenIfNoListener = true; }
            if (fireEventsOnRegistration === void 0) { fireEventsOnRegistration = true; }
            var _this = _super.call(this) || this;
            _this.linkSites = new ecs.Bag();
            _this.decoratedLinkSite = new ecs.Bag();
            _this._requireListener = !processSitesEvenIfNoListener;
            _this._fireEventsOnRegistration = fireEventsOnRegistration;
            return _this;
        }
        EntityLinkManager.prototype.processSystem = function () {
            if (this._requireListener) {
                this.processLink(this.decoratedLinkSite);
            }
            else {
                this.processLink(this.linkSites);
            }
        };
        EntityLinkManager.prototype.processLink = function (sites) {
            for (var i = 0; i < sites.size(); i++) {
                sites.get(i).process();
            }
        };
        return EntityLinkManager;
    }(ecs.BaseEntitySystem));
    ecs.EntityLinkManager = EntityLinkManager;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var LinkSite = (function () {
        function LinkSite(world, type, field) {
            this.type = type;
            this.field = field;
            this.mapper = world.getMapper(type.getType());
        }
        LinkSite.prototype.inserted = function (entities) {
            var ids = entities.getData();
            for (var i = 0, s = entities.size(); s > i; i++) {
                this.insert(ids[i]);
            }
        };
        LinkSite.prototype.removed = function (entities) {
            var ids = entities.getData();
            for (var i = 0, s = entities.size(); s > i; i++) {
                this.remove(ids[i]);
            }
        };
        LinkSite.prototype.process = function () {
            var entities = this.subscription.getEntities();
            var ids = entities.getData();
            for (var i = 0, s = entities.size(); s > i; i++)
                this.check(ids[i]);
        };
        return LinkSite;
    }());
    ecs.LinkSite = LinkSite;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var ClassReflection = (function () {
        function ClassReflection() {
        }
        ClassReflection.isAssignableFrom = function (c1, c2) {
            return c2 instanceof c1;
        };
        return ClassReflection;
    }());
    ecs.ClassReflection = ClassReflection;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var Field = (function () {
        function Field() {
        }
        return Field;
    }());
    ecs.Field = Field;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var Bag = (function () {
        function Bag(capacity) {
            if (capacity === void 0) { capacity = 64; }
            this._size = 0;
            this._data = new Array(capacity);
        }
        Bag.prototype.get = function (index) {
            return this._data[index];
        };
        Bag.prototype.getData = function () {
            return this._data;
        };
        Bag.prototype.set = function (index, e) {
            if (index >= this._data.length)
                this.grow(Math.max((2 * this._data.length), index + 1));
            this._size = Math.max(this._size, index + 1);
            this.unsafeSet(index, e);
        };
        Bag.prototype.ensureCapacity = function (index) {
            if (index >= this._data.length)
                this.grow(index + 1);
        };
        Bag.prototype.unsafeSet = function (index, e) {
            this._data[index] = e;
        };
        Bag.prototype.getCapacity = function () {
            return this._data.length;
        };
        Bag.prototype.size = function () {
            return this._size;
        };
        Bag.prototype.isEmpty = function () {
            return this._size == 0;
        };
        Bag.prototype.add = function (e) {
            if (this._size == this._data.length)
                this.grow(this._data.length * 2);
            this._data[this._size++] = e;
        };
        Bag.prototype.contains = function (e) {
            for (var i = 0; this._size > i; i++) {
                if (e == this._data[i])
                    return true;
            }
            return false;
        };
        Bag.prototype.grow = function (newCapacity) {
            var newData = new Array(newCapacity);
            for (var k in this._data)
                newData.push(this._data[k]);
            this._data = newData;
        };
        return Bag;
    }());
    ecs.Bag = Bag;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var BitVector = (function () {
        function BitVector(nbits) {
            this._words = [0];
            if (nbits != undefined)
                this.checkCapacity(nbits.rightMove(6));
        }
        BitVector.prototype.get = function (index) {
            var word = index.rightMove(6);
            return word < this._words.length && (this._words[word] & (1 << index)) != 0;
        };
        BitVector.prototype.set = function (index, value) {
            if (value === void 0) { value = true; }
            if (value) {
                var word = index.rightMove(6);
                this.checkCapacity(word);
                this._words[word] |= 1 << index;
            }
            else {
                this.clear(index);
            }
        };
        BitVector.prototype.unsafeGet = function (index) {
            return (this._words[index.rightMove(6)] & (1 << index)) != 0;
        };
        BitVector.prototype.unsafeSet = function (index, value) {
            if (value === void 0) { value = true; }
            if (value) {
                this._words[index.rightMove(6)] |= 1 << index;
            }
            else {
                this.unsafeClear(index);
            }
        };
        BitVector.prototype.unsafeClear = function (index) {
            this._words[index.rightMove(6)] &= ~(1 << index);
        };
        BitVector.prototype.clear = function (index) {
            if (index == undefined) {
                var word = index.rightMove(6);
                if (word >= this._words.length)
                    return;
                this._words[word] &= ~(1 << index);
            }
            else {
                for (var i = 0; i < this._words.length; i++) {
                    this._words[i] = 0;
                }
            }
        };
        BitVector.prototype.length = function () {
            var bits = this._words;
            for (var word = bits.length; word >= 0; --word) {
                var bitsAtWord = bits[word];
                if (bitsAtWord != 0)
                    return (word << 6) + 64 - this.numberOfLeadingZeros(bitsAtWord);
            }
            return 0;
        };
        BitVector.prototype.isEmpty = function () {
            var bits = this._words;
            var length = bits.length;
            for (var i = 0; i < length; i++) {
                if (bits[i] != 0)
                    return false;
            }
            return true;
        };
        BitVector.prototype.toIntBag = function (out) {
            if (this.isEmpty()) {
                out.setSize(0);
                return out;
            }
            var count = this.prepareBag(out, 2);
            var data = out.getData();
            for (var i = 0, index = 0; count > index; i++) {
                var bitset = this._words[i];
                var wordBits = i << 6;
                while (bitset != 0) {
                    var t = bitset & -bitset;
                    data[index] = wordBits + this.bitCount(t - 1);
                    bitset ^= t;
                    index++;
                }
            }
            return out;
        };
        BitVector.prototype.toIntBagIdCid = function (cm, out) {
            if (this.isEmpty()) {
                out.setSize(0);
                return out;
            }
            var count = this.prepareBag(out, 2);
            var data = out.getData();
            for (var i = 0, index = 0; count > index; i++) {
                var bitset = this._words[i];
                var wordBits = i << 6;
                while (bitset != 0) {
                    var t = bitset & -bitset;
                    var id = wordBits + this.bitCount(t - 1);
                    data[index] = id;
                    data[index + 1] = cm.getIdentity(id);
                    index += 2;
                    bitset ^= t;
                }
            }
            return out;
        };
        BitVector.prototype.prepareBag = function (out, elementsPerEntry) {
            var count = elementsPerEntry * this.cardinality();
            out.ensureCapacity(count);
            out.setSize(count);
            return count;
        };
        BitVector.prototype.cardinality = function () {
            var count = 0;
            for (var i = 0; i < this._words.length; i++) {
                count += this.bitCount(this._words[i]);
            }
            return count;
        };
        BitVector.prototype.bitCount = function (i) {
            i = i - (i.rightMove(1) & 0x5555555);
            i = (i & 0x33333333) + ((i.rightMove(2) & 0x33333333));
            i = (i + (i.rightMove(4))) & 0x0f0f0f0f;
            i = i + i.rightMove(8);
            i = i + i.rightMove(16);
            return i & 0x3f;
        };
        BitVector.prototype.numberOfLeadingZeros = function (i) {
            if (i == 0)
                return 32;
            var n = 1;
            if (i.rightMove(16) == 0) {
                n += 16;
                i <<= 16;
            }
            if (i.rightMove(24) == 0) {
                n += 8;
                i <<= 8;
            }
            if (i.rightMove(28) == 0) {
                n += 4;
                i <<= 4;
            }
            if (i.rightMove(30) == 0) {
                n += 2;
                i <<= 2;
            }
            n -= i.rightMove(31);
            return n;
        };
        BitVector.prototype.ensureCapacity = function (bits) {
            this.checkCapacity(bits.rightMove(6));
        };
        BitVector.prototype.checkCapacity = function (len) {
            if (len >= this._words.length) {
                var newBits = new Number[len + 1];
                this._words.copy(0, newBits, 0, this._words.length);
                this._words = newBits;
            }
        };
        return BitVector;
    }());
    ecs.BitVector = BitVector;
})(ecs || (ecs = {}));
Array.prototype.copy = function (srcPos, dest, destPos, length) {
    for (var i = srcPos, offset = 0; i < length; i++, offset++) {
        this[i] = dest[destPos + offset];
    }
};
Number.prototype.rightMove = function (pos) {
    var value = Number(this);
    if (pos != 0) {
        var mask = Number.MAX_VALUE;
        value = value >> 1;
        value = value & mask;
        value = value >> pos - 1;
    }
    return value;
};
var ecs;
(function (ecs) {
    var Map = (function () {
        function Map(init) {
            this._keys = [];
            this._values = [];
            for (var i = 0; i < init.length; i++) {
                this._keys.push(init[i].key);
                this._values.push(init[i].value);
            }
        }
        Map.prototype.get = function (key) {
            for (var i = 0; i < this._keys.length; i++) {
                if (JSON.stringify(this._keys[i]) == JSON.stringify(key))
                    return this._values[i];
            }
            return null;
        };
        Map.prototype.add = function (key, value) {
            this._keys.push(key);
            this._values.push(value);
        };
        Map.prototype.remove = function (key) {
            var index = this._keys.indexOf(key, 0);
            this._keys.splice(index, 1);
            this._values.splice(index, 1);
        };
        Map.prototype.keys = function () {
            return this._keys;
        };
        Map.prototype.values = function () {
            return this._values;
        };
        Map.prototype.clear = function () {
            this._keys.splice(0);
            this._values.splice(0);
        };
        return Map;
    }());
    ecs.Map = Map;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var MathUtils = (function () {
        function MathUtils() {
        }
        MathUtils.clamp = function (value, min, max) {
            value = (value > max) ? max : value;
            value = (value < min) ? min : value;
            return value;
        };
        return MathUtils;
    }());
    ecs.MathUtils = MathUtils;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var NumberBag = (function () {
        function NumberBag(capacity) {
            if (capacity === void 0) { capacity = 64; }
            this._size = 0;
            this._data = new Array(capacity);
        }
        NumberBag.prototype.get = function (index) {
            if (index >= this._size) {
                var message = "tried accessing element " + index + "/" + this._size;
                throw new Error(message);
            }
            return this._data[index];
        };
        NumberBag.prototype.size = function () {
            return this._size;
        };
        NumberBag.prototype.setSize = function (size) {
            this._size = size;
        };
        NumberBag.prototype.getData = function () {
            return this._data;
        };
        NumberBag.prototype.isEmpty = function () {
            return this._size == 0;
        };
        NumberBag.prototype.ensureCapacity = function (index) {
            if (index >= this._data.length)
                this.grow(index + 1);
        };
        NumberBag.prototype.grow = function (newCapacity) {
            var oldData = this._data;
            this._data = new Number[newCapacity];
            oldData.copy(0, this._data, 0, oldData.length);
        };
        NumberBag.prototype.contains = function (value) {
            for (var i = 0; this._size > i; i++) {
                if (value == this._data[i])
                    return true;
            }
            return false;
        };
        return NumberBag;
    }());
    ecs.NumberBag = NumberBag;
})(ecs || (ecs = {}));
var ecs;
(function (ecs) {
    var NumberDeque = (function () {
        function NumberDeque(capacity) {
            if (capacity === void 0) { capacity = 64; }
            this._size = 0;
            this._elements = new Array(capacity);
        }
        NumberDeque.prototype.contains = function (e) {
            for (var i = 0; this._size > i; i++) {
                if (e == this._elements[this.index(i)])
                    return true;
            }
            return false;
        };
        NumberDeque.prototype.get = function (index) {
            return this._elements[this.index(index)];
        };
        NumberDeque.prototype.size = function () {
            return this._size;
        };
        NumberDeque.prototype.getCapacity = function () {
            return this._elements.length;
        };
        NumberDeque.prototype.isEmpty = function () {
            return this._size == 0;
        };
        NumberDeque.prototype.add = function (e) {
            if (this._size == this._elements.length)
                this.grow((this._elements.length * 7) / 4 + 1);
            this._elements[this.index(this._size++)] = e;
        };
        NumberDeque.prototype.set = function (index, e) {
            if (index >= this._elements.length) {
                this.grow((index * 7) / 4 + 1);
            }
            this._size = Math.max(this._size, index + 1);
            this._elements[this.index(index)] = e;
        };
        NumberDeque.prototype.ensureCapacity = function (index) {
            if (index >= this._elements.length)
                this.grow(index);
        };
        NumberDeque.prototype.popFirst = function () {
            this.assertNotEmpty();
            var value = this._elements[this._beginIndex];
            this._beginIndex = (this._beginIndex + 1) % this._elements.length;
            this._size--;
            return value;
        };
        NumberDeque.prototype.assertNotEmpty = function () {
            if (this._size == 0)
                throw new Error("Deque is empty");
        };
        NumberDeque.prototype.grow = function (newCapacity) {
            var newElement = new Number[newCapacity];
            for (var i = 0; i < this._size; i++)
                newElement[i] = this.get(i);
            this._elements = newElement;
            this._beginIndex = 0;
        };
        NumberDeque.prototype.index = function (relativeIndex) {
            return (this._beginIndex + relativeIndex) % this._elements.length;
        };
        return NumberDeque;
    }());
    ecs.NumberDeque = NumberDeque;
})(ecs || (ecs = {}));
